<?php

namespace app\api\controller;

use app\common\controller\Api;
use app\common\model\Config;
use app\common\model\MoneyLog;
use app\common\model\Strategy;
use app\common\model\ShareStrategy;
use app\common\model\StrategyTransaction;
use app\common\model\User;
use think\Db;
use think\Log;

class Job extends Api
{
    // 无需登录的接口,*表示全部
    protected $noNeedLogin = ['*'];
    // 无需鉴权的接口,*表示全部
    protected $noNeedRight = ['*'];

    //获取股票信息
    protected function stockInfo($data){
        $returnData = getStockInfo($data);
        return $returnData;
    }
    
    
    //自动补仓
    public function autoAdd(){
        if( !isPayTime() ){
            $this->error('不在交易时间');
        }
        $strategyList = Strategy::where(['status'=>1])->select();
        $allNoList = $strategyList->column('all_no');
        $stockList = getStockInfo($allNoList);
        $conList = Config::getVal(['strategy','commission','stamp_duty','transfer_fee','management_expense','add_warehouse']);
        /** @var Strategy $strategyInfo */
        foreach ( $strategyList as $strategyInfo ){
            $stockInfo = $stockList[$strategyInfo->all_no];
            Log::info('开始处理:'.$strategyInfo->id);
            try {
                //每次保存收益信息
                $strategyInfo->statistics($stockInfo)->save();
                $this->handleAutoAdd($strategyInfo,$stockInfo,$conList);
            }catch (\Exception $e) {
                //异常跳过不处理，防止卡主下一个订单
                Log::error($e->getMessage());
            }
            Log::info('处理完毕:'.$strategyInfo->id);
        }
    }

    //处理单个自动补仓
    protected function handleAutoAdd(Strategy $strategyInfo,$stockInfo,$conList){
        //计算盈余
        $oldStrategyInfo = $strategyInfo->statistics($stockInfo,false)->addSumPrice($stockInfo);
//        dump($oldStrategyInfo->income_ratio );

        //亏损超过百分之七十自动补仓
        if( $oldStrategyInfo->income_ratio > -0.8){
            Log::info("亏损不超过80%，无需处理");
            return ;
        }
        //计算需要补仓的股数 需要满足补充之后的保证金    是市值的5% 每次累加100计算股数
        $num = $this->countAddNum($oldStrategyInfo,$stockInfo);
        $userInfo = $strategyInfo->user;
        //计算需要补交的保证金
        $addEarnestMoney = $stockInfo['price'] * $num / 10;
        //建仓费
        $addWarehouse = $addEarnestMoney * 10 * $conList['add_warehouse'];
        //管理费
        $managementExpense = $strategyInfo->is_auto == 1 ? $addEarnestMoney * $conList['management_expense'] * 0.01 * 10: 0;
        Db::startTrans();
        try{
            //余额不足以续交保证金，自动平仓
            if( $userInfo->money < ($addEarnestMoney+$addWarehouse+$managementExpense) ){
                Log::info("余额不足:{$userInfo->money},自动平仓");
                $strategyInfo->pay($stockInfo,$conList);
            }else{
                //自动加仓
                Log::info('自动加仓');
                $strategyInfo->addNum($stockInfo,$num,$conList);
            }
            Db::commit();
        }catch (\Exception $e){
            Db::rollback();
            throw $e;
        }

    }

    /**
     * 计算需要累加多少股可以达到5% 保证金
     * 每次累加100股计算
     * @param Strategy $oldStrategyInfo
     * @param $stockInfo
     * @param $initNum
     * @return float|int
     */
    protected function countAddNum(Strategy $oldStrategyInfo,$stockInfo,$initNum = 0){
        //记录初始股数
        if( $initNum == 0 ){
            $initNum = $oldStrategyInfo->lever_num;
            //结算金额
            $oldStrategyInfo->income_log += $oldStrategyInfo->income;//记录历史盈余
        }
        //累加股数 数值变动
        $oldStrategyInfo->num += 10;
        $oldStrategyInfo->lever_num += 100;
        $earnestMoney = $stockInfo['price'] * 10;//保证金
        $oldStrategyInfo->earnest_money += $earnestMoney;
        $oldStrategyInfo->buy_price = $stockInfo['price'];
        //再次计算收益
        $oldStrategyInfo->statistics($stockInfo);

        //达到百分之五十证明亏损值要大于-0.5
        if( $oldStrategyInfo->income_ratio >= -0.5 ){
            return $oldStrategyInfo->lever_num - $initNum;
        }
        //如果达不到对应股数，则继续累加
        return $this->countAddNum($oldStrategyInfo,$stockInfo,$initNum);
    }


    //每天自动管理  未勾选自动卖出 勾选自动管理收取管理费用
    public function autoManage(){
        
        if( !isPayTime() ){
            //$this->error('不在交易时间');
            return;
        }
        $strategyList = ShareStrategy::where(['status'=>1])->select();
        
        
        $allNoList = $strategyList->column('all_no');
        
        $userIds = $strategyList->column('user_id');
        
        $userInfos = User::where(['id'=>['in',$userIds]])->select();
        
        $stockList = getStockInfo($allNoList);
        //echo json_encode($stockList);die;
        
        $conList = Config::getVal(['commission','stamp_duty','transfer_fee','management_expense']);
        
        $managementExpense = 0;
        $strategyInfo1 = [];
        foreach ($userInfos as $key => $user){
            
            $managementExpense = 0;
            foreach ($strategyList as $strategyInfo){
                
                if($user['id'] == $strategyInfo['user_id']){
                    
                    $managementExpense += intval($strategyInfo['total_lever_num'])*floatval($stockList[$strategyInfo['all_no']]['price'])*floatval($conList['management_expense']);
                }
            }
            Log::info('开始处理:'.$strategyInfo->id);
            Db::startTrans();
            try {
            
                if($strategyInfo['is_auto'] == 1 && $managementExpense <= $user['money']){
                    updateMoney($userInfos[$key],$managementExpense*-1,'管理费');
                }else{
                    //用户余额不够扣管理费就自动平仓一支盈利最少的股票
                    $this->autoPay($userInfos[$key]);
                }
                Db::commit();
            }catch (\Exception $e) {
                Db::rollback();
                //异常跳过不处理，防止卡主下一个订单
                Log::error($e->getMessage());
            }
            Log::info('处理完毕:'.$strategyInfo->id);
        }
    }
    
    //账户余额不够扣管理费的自动给盈利最少的股票平仓
    protected function autoPay($userInfo){
        
        $strategyList = ShareStrategy::where(['status'=>1,'user_id'=>$userInfo['id']])->select();
        
        //获取各种手续费金额信息
        $conList = Config::getVal(['commission','stamp_duty','transfer_fee']);
        //所持有股票编号
        $allNoList = $strategyList->column('all_no');
        
        //获取股票信息
        $stockInfo = $this->stockInfo($allNoList);
        
        $arr = array();
        foreach ($strategyList as $key => $strategy){
            
            //平均买价
            $buy_price = floatval(floatval($strategy['total_earnest'])/intval($strategy['total_lever_num'])*10);
            //每股盈亏
            $profit = floatval($stockInfo[$strategy['all_no']]['price']) - $buy_price;
            //总盈亏
            $sumProfit = $profit * intval($strategy['total_lever_num']);
            //组装 总盈亏 =>策略ID  键值对
            $arr[$sumProfit] = $strategy['id'];
        }
        //排序 键升序
        ksort($arr);
        //取数组内第一个键的值
        $mixSumProfitId = reset($arr);
        //被选中平仓的策略
        $payLtrategy = ShareStrategy::where(['id'=>$mixSumProfitId])->find();
        
        $strategy = array();
        
        //策略表里总保证金要扣除的保证金
        $earnest = intval($payLtrategy->total_earnest);
        $strategy['id'] = $payLtrategy->id;
        $strategy['total_lever_num'] = 0;
        $strategy['total_earnest'] =0;
        $strategy['can_use_num'] = 0;
        $strategy['status'] = 0;
        
        $transaction = array();
        //创建策略交易记录
        $strategyTransaction                = new StrategyTransaction();
        $transaction['user_id']       = $userInfo->id;
        $transaction['strategy_id']   = $payLtrategy->id;
        $transaction['type']          = 'autoReduce';
        $transaction['buy_price']     = floatval($payLtrategy->total_earnest)/floatval($payLtrategy->total_lever_num)*10;
        $transaction['pay_price']     = floatval($stockInfo[$payLtrategy['all_no']]['price']);
        $transaction['lever_num']     = $payLtrategy->total_lever_num;
        $transaction['name']          = $payLtrategy->name;
        $transaction['no']            = $payLtrategy->all_no;
        //保证金记录
        $transaction['earnest']       = $earnest;
        $transaction['pay_time']      = time();
        $transaction['buy_time']      = $payLtrategy->createtime;
        $transaction['createtime']    = time();
        $transaction['updatetime']    = time();
            
            
        Db::startTrans();
        try {
            //修改策略表信息 
            ShareStrategy::update($strategy);
            //持有股票的保证金平仓后要退回到可用资金
            updateMoney($userInfo,$earnest,'保证金');
            //新增交易记录
            $strategyTransaction->insert($transaction);
                Db::commit();
        }catch (\Exception $e) {
            Db::rollback();
            //异常跳过不处理，防止卡主下一个订单
            Log::error($e->getMessage());
        }
        return;
    }

    //余额宝
    public function balance(){
        //查找当天已经获取过的数据
        $userIdList = MoneyLog::whereTime('createtime','d')
            ->where(['memo'=>'余额宝'])
            ->field('user_id')
            ->select()
            ->column('user_id');
        $userList = \app\common\model\User::where(['status'=>'normal'])->whereNotIn('id',$userIdList)->select();
        $conList = Config::getVal(['balance_income']);
        /** @var \app\common\model\User $userInfo */
        foreach ( $userList as $userInfo ){
            if( $userInfo->money <= 0 ){
                continue;
            }
            $money = $userInfo->money * $conList['balance_income'];
            try{
                updateMoney($userInfo,$money,'余额收益');
            }catch (\Exception $e){
                Log::error("{$userInfo->id}:".$e->getMessage());
            }
        }
    }

    /**
     * 更新平仓可用
     */
    public function jhrw()
    {
     
        $stocks1 = ShareStrategy::where(['status'=>1])->select()->toArray();
        
        foreach ($stocks1 as $key => $value){
            $keyong = 0;
            $jiaoyi = StrategyTransaction::where(['strategy_id'=>$value['id']])->column('id,strategy_id,lever_num,buy_time,type');
            foreach ($jiaoyi as $k => $val){
                if(date('Y-m-d') > date('Y-m-d',$val['buy_time'])){

                    if($val['type'] == 'add' || $val['type'] == 'new'){
                        $keyong += $val['lever_num'];
                    }else{
                        $keyong -= $val['lever_num'];
                    }
                    //echo $keyong;
                }
            }

           $stocks1[$key]['can_use_num'] = $keyong;
           
        }

        Db::startTrans();
        try {
            foreach ($stocks1 as $key => $value){
                
                ShareStrategy::update([
                    'id'=>$value['id'],
                    'can_use_num'=>$value['can_use_num']
                    ]);
            }
            echo '添加可用成功';
            Db::commit();
        }catch (\Exception $e){
            Db::rollback();
            Log::error("添加可用失败:".$e->getMessage());
        }
    }

}